#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <memory>
#include <unistd.h>
#include "Socket.hpp"
#include "Acceptor.hpp"
#include <sys/select.h>
#define MAX_SIZE 64
using namespace socket_ns;

static const int default_val = -1;
using ReadEventCallBack_t  = std::function<void(int)>;
using WriteEventCallBack_t  = std::function<void(int)>;
using AcceptEventCallBack_t  = std::function<void(SelectServer*)>;
class SelectServer
{
private:
    // 辅助数组
    int _fd_array[MAX_SIZE];
    // 监听套接字
    Acceptor _listensockfd;
    bool _isrunning;
    //设置回调
    ReadEventCallBack_t _read_cb;
    WriteEventCallBack_t _write_cb;
    AcceptEventCallBack_t _accept_cb;
public:
    SelectServer(uint16_t port,const ReadEventCallBack_t& read_cb,const WriteEventCallBack_t& write_cb,const AcceptEventCallBack_t& accept_cb) 
        :_listensockfd(port),_isrunning(false),
        _read_cb(read_cb),
        _write_cb(write_cb),
        _accept_cb(accept_cb)
    {
    }
    void Init()
    {
        // 将监听套接字加入监视数组
        _fd_array[0] = _listensockfd.ListenFd();
        for (int i = 1; i < MAX_SIZE; i++)
        {
            _fd_array[i] = default_val;
        }
    }
    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            int maxfd = 0;
            fd_set reads;
            FD_ZERO(&reads);
            for (int i = 0; i < MAX_SIZE; i++)
            {
                if (_fd_array[i] == default_val)
                    continue;
                FD_SET(_fd_array[i], &reads);
                // update maxfd
                if (maxfd > _fd_array[i])
                {
                    maxfd = _fd_array[i];
                }
            }
            struct timeval timeout;
            timeout.tv_sec = 3;
            timeout.tv_usec = 0;
            int ret = ::select(maxfd + 1, &reads, nullptr, nullptr, &timeout);
            // 如果有描述符就绪，select会将填充进去的reads填充已就绪的描述符！
            switch (ret)
            {
            case 0:
                LOG(INFO, "已超时!\n");
                break;
            case -1:
                LOG(ERROR, "本次select异常!\n");
                break;
            default:
                // 分配器
                Dispatcher(reads);
                break;
            }
        }
    }
    // 分配器
    void Dispatcher(fd_set &reads)
    {
        bool isfull = true;
        for (int i = 0; i < MAX_SIZE; i++)
        {
            if (_fd_array[i] == default_val)
                continue;
            if (_listensockfd.ListenFd() == _fd_array[i])
            {
                // 说明是监听套接字就绪！
                // 转发给Acceptor！
                // int fd = _listensockfd.Accept();
                // if(fd < 0)
                // {
                //     //遍历找到空闲的fd_set的位置
                //     for(int i = 0;i<MAX_SIZE;i++)
                //     {
                //         if(_fd_array[i] == default_val)
                //         {
                //             _fd_array[i] = fd;
                //             isfull = false;
                //             break;
                //         }
                //     }
                //     //如果满了就关闭该客户端连接
                //     if(isfull)
                //     {
                //         ::close(fd);
                //         LOG(WARNING,"Select已满!\n");
                //     }
                // }
                _accept_cb(this);
            }
            else
            {
                // 说明是一个客户端的IO事件就绪！
                // 转发给事件处理器！EventLoop---TODO
                _read_cb( _fd_array[i]);
            }
        }
    }
    ~SelectServer()
    {
    }
};